-| Win87xx 1.18 |- by: Xacker 02.01.2005

{ Best view under IE6? Maximized - Font enlarged for blindies! }

Overview:
In this essay im gonna show you how you can crack with some luck every setup file that requires password or serial upon installation to proceed.
These kinds of setup files (such as programs packed with InstallShield, Inno SFX etc..) works approximately the same, they unpack some files to the disk then execute the real setup file, thus, the real setup file is actually embedded within the setup package.
Sometimes the programmers attend to unpack only few files or only part of the program that you wanna install as another part of protection. Those different kind of protections are all alike when you get to crack 'em and i hope this essay will show ya how you can accomplish that.

Things you need to know:
You need to understand how CreateFileA, WriteFile functions work, thats all!

Things you should obtain:
- SoftIce (i use 3.24 on win9x)
- PE-Editor (i use lordpe)
- HexEditor (old times Hiew :p)
- Win87xx 1.18 (ofcourse silly!)

Lets begin:
In order to reverse such programs you first need to find where the the checking routine is (cmp goodserial,badserial -> jne getlost) and to be more spicific you need to know the opcodes of those commands, why? later on.
So, how to find where the checking routine is? open up the setup file and click next to proceed, WOOPS! you have to enter a password to continue installing the program, enter anything.. no no not 'anything', i mean anything as password hehe, i enter 'this1234pass' and i hit next, a msgbox displayed 'The password you entered is not correct. Please try again'.
Now open sice, in fact there is two functions we can set a bp on, the 1st one works only on 9x boxes coz we will set the bp on HMEMCPY function, while the other works on both NT & 9x coz we will set the bp on SLEEP, the two functions takes you into the heart of the protection, the hmemcpy takes you right before the checking routine while the sleep ofcoz takes you after the comparsion has been done so, pick up what suites your [O]h[S]ystem!

bpx hmemcpy || bpx sleep:
Go ahead and enter any password like 'this1234pass' then set a bp in sice on hmemcpy, F5 to go back to the program and hit Next to break on this function.
after you do so press F12 for 12 times to pass the RET, now you will find your self on the following addr:

4407BA:	mov	eax,[ebp-4]		; u r here
	call	403588
	push	eax
	lea	eax,[ebp-4]
	call	403758
	pop	edx
	call	42E678			; interesting call
	cmp	eax,[4511dc]		; compare eax value with whats on 4511dc
	setz	bl			; set zero to bl if they dont match
	test	bl,bl			' bl = 0 ?
	jz	getlost			; -> getlost
reged:	mov	byte ptr [451260],0	; else continue
	mov	eax,[ebp+8]
	mov	eax,[eax-4]
	mov	eax,[eax+1e4]
	mov	edx,edx
	call	421e60
	jmp	continue
getlost:
	blah blah
	blah blah
	call	Sleep
	blah blah
	blah blah
	call	MessageBoxA
	jmp	stupidcracker

Really simple algorithm when you come to test it, you only need to patch that jz into jnz and you can continue your installation. But doing so is limited to your machine and you have to go through all debugging again on next installation! so what are you gonna do?

If you check the file that you are in after you break on any of the previous apis you will notice that you are in something like 'Insxxxx' where xxxx is a rand hex number that changes from one execution to another!
That file is created when you start installation in the Temp dir and its deleted after you close it. So, our lil checking routine is in that file, but we cant patch it there coz the file will be deleted, and we cant just copy it, patch it and set it there on next installation hoping the program will pick it instead of the one which it creates! so again...

What are you gonna do?
What we are going to do is very simple, we will think logically about this, so lets review back what we know about the program:

- The checking routine is in the Insxxxx.tmp file.
- That file is being created in the the temp dir.
- We cant patch that file coz it will be very stupid!

The weakness of this protection is that the setup file has to WRITE the bytes of the protection algorithm to the Insxxxx.tmp file and there is where we are gonna strike! we can simply interrupt the writing process, and change the bytes before they get written to the file which creates a patched file for us!
Ofcourse this operation it self is also limited coz you will have to interrupt the process each time you wanna install the program so to pass such thing we will inject a code in the program that will do that for us but before we need to know the opcodes of our checking routine, and in this case its the opcodes of the JZ command but because there will be alot of JZs with the same opcodes we will take search for 4 bytes instead of 2, this insures that we get the correct JZ and we can save em in a register when we wanna search for 'em :)
Go back now to the program and debug it to locate the opcodes, after you view the addr of the JZ note down the 1st four bytes that you will get in the data window, they will be like this: [74 1C C6 05]

(flip) (flip) <- searching in my win32api manual for the usage of CreateFileA && WriteFile, (flip).. here is how to use 'em:

The CreateFileA returns the handle that can be used to access the object.

 HANDLE CreateFile( 
  
      LPCTSTR   lpFileName ,    	 		 // pointer to name of the file     
     DWORD   dwDesiredAccess ,    	 		 // access (read-write) mode     
     DWORD   dwShareMode ,    	 			 // share mode     
     LPSECURITY_ATTRIBUTES   lpSecurityAttributes ,    	 // pointer to security attributes     
     DWORD   dwCreationDistribution ,       // how to create     
     DWORD   dwFlagsAndAttributes ,    	    // file attributes     
     HANDLE   hTemplateFile      	    // handle to file with attributes to copy      
    ); 
The WriteFile function writes data to a file and is designed for both synchronous and asynchronous operation.
The function starts writing data to the file at the position indicated by the file pointer.
After the write operation has been completed, the file  pointer is adjusted by the number of bytes
actually written, except when the file is opened with FILE_FLAG_OVERLAPPED. If the file handle was created
for overlapped input and output (I/O), the application must adjust the position of the file pointer after
the write operation is finished.  
  
 BOOL WriteFile( 
  
      HANDLE   hFile ,    	 	    // handle to file to write to     
     LPCVOID   lpBuffer ,    	            // pointer to data to write to file     
     DWORD   nNumberOfBytesToWrite ,        // number of bytes to write     
     LPDWORD   lpNumberOfBytesWritten ,     // pointer to number of bytes written     
     LPOVERLAPPED   lpOverlapped      	    // pointer to structure needed for overlapped I/O    
    );  

So obviously the CreateFileA function must be called to return the handle of the file that is being created then the program can calls WriteFile providing the handle and sets the number of bytes to write to that file. The thing that you need to know that the program must write the data in parts due to memory strictions.
We will go back to our program now and (before we run the setup) we will set a bp on CreateFileA then run it.
You will have to break 3 times to get to the right call, make sure you are about to create the Insxxxx.tmp file by viewing EAX value 'd eax'
After you reach the right call clear the bp you sat and set one on WriteFile, before you press F11 take a look @ the registers and note down the values, [EAX=10000 || EBX=40FDB8 || ECX=10000 || EDX=00000000 || ESI=BA0004 || EDI=10000 || EBP=64AD64 || ESP=64FC9C], now press F11 to get out of the call then scroll abit to the top and you will see this:

push	00		; lpOverlapped? no
push	eax		; lpNumberOfBytesWritten = 10000
mov	eax,[ebx+08]
mul	ecx
push	eax		; nNumberOfBytesToWrite = 10000
push	esi		; lpBuffer
push	dword ptr [ebx]	; hFile
call	WriteFile

Now we will interrupt the data so how we do that? we will use the 's'earch command in sice, it allows to search for certain bytes and its used like this:

s BufferToSearchIn L BoundaryToSearchIn ,xx,xx (return)

You have to replace BufferToSearchIn with esi, replace BoundaryToSearchIn with ffffff (it tells sice to search in all the buffer), replace xx with the bytes we wanna search for ,74,1C,C6,05
When you enter this command you will get either 'Pattern not found' or 'Patten found at ....', so enter that command and see the result, if you didnt find your bytes then press F5 to break again on the next part of data to be written then use the command again, repeat that till you see 'Pattern found at 017F:BA2C34 (2C30)'
We only care about the number between () coz its the offset of the bytes being written, why do we need this offset? we need it to reach the bytes in our injected code, they are simply @ esi+2c30 !

Now ive found the bytes, whats next?
We will search now for a place where we can redirect the execution flow to a cave we choose in order to inject our code. Lets first search for a suitable cave, i found one @ 40C570 (90 bytes in the .code section, but the .code section flag is Read/Execute only so change the characteristicts to E0000020)
Now where can we redirect the flow? we will do that @ 403C80, yes we will change the call to writefile to our jmp 40c570 so set a bp on WriteFile -> F11, clear all the bps, set new one @ 403c80 and break on it, then type 'e 403c80 e9 eb 88 00 00 (return)'
Now press F10 to goto that location, we will inject a code now that searchs the written data for our bytes and when it finds 'em it will patch and write 'em to the file. This code will be the following:

	pushad					; saves registers values to restore l8r
	mov	eax, [esi+2c30]			; store bytes @ esi+2c30 in eax
	cmp	eax, 05C61C74			; are they identical?
	jne	40c577				; pass our patch if not our bytes
	mov	word ptr [esi+2c30], 9090 	; write NOP instead of JZ :)
40c577: popad					; restore registers values
	call	4011dc				; call writefile
	jmp	403c85				; jump back to normal execution flow

You can set a bp on 40c570 and do 'd esi+2c30' then keep pressing F5 and you can see how your bytes are being compared with the ones we want then how the patch will be applied.. but thats not all of it coz after the program finishs calling writefile a msgbox appears telling you that the file is corrupted, its not, thats bcoz our modification but bcoz its just a msgbox you can simply remove it by patching addr 40C30E to JMP before you start your reversing journey :)

Now how can i get a cracked copy of the program? you cant dump the process ofcourse coz its not in one file but you have to take the opcodes of the code you have injected and using any hexeditor you admire :p you have to make the changes, it should be something like this with lordpe:

In the end:
Greetings goes out to: Fusion members , chik and who ever ive learnt anything from

Back to the top - E-mail the author Visit Fusion WebSiDe!